package transactiontest;

import org.junit.Test;
import utils.JDBCUtils;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * @author DuJiabao
 * @create 2021-01-15 22:46
 * 事务测试
 * <p>
 * 隔离级别：
 * READ-UNCOMMITTED: 多个事务之间，就算该事务没有提交，其他事务也会看到该事务修改的内容
 * READ-COMMITTED: 多个事务之间，只有该事务提交了事务，其他事务才会更新内容
 * REPEATABLE-READ: 多个事务之间，即使其他事务更新了内容，只要该事务没有关闭当前事务，都不会更新自己的内容。但其他事务的插入操作，会更新。
 * SERIALIZABLE: 不能发生并发行为。只有一个事务退出之后，另一个事务才能进入。
 */
public class TransactionTest {
  @Test
  public void test() {
    Connection conn = null;
    int transfer = 100;
    String sql = "update new_table3 set balance = balance + ? where last_name=?";
    try {
      conn = JDBCUtils.getConnection();
      conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // 设置隔离级别
      System.out.println(conn.getTransactionIsolation()); //读取当前隔离级别
      conn.setAutoCommit(false);  // 关闭自动提交
      JDBCUtils.updateDatabase(conn, sql, 100, "amy");
      //System.out.println(100 / 0); // 模拟错误
      JDBCUtils.updateDatabase(conn, sql, -100, "john");
      conn.commit();  // 所有任务执行完，没有错误了，再提交
    } catch (Exception e) {
      e.printStackTrace();
      try {
        if (conn != null) {
          conn.rollback();  // 发生错误就回滚
        }
      } catch (SQLException throwables) {
        throwables.printStackTrace();
      }
    } finally {
      try {
        if (conn != null) {
          conn.setAutoCommit(true);  // 重新开启自动连接
        }
      } catch (SQLException throwables) {
        throwables.printStackTrace();
      }
      JDBCUtils.closeSource(conn);  // 关闭连接
    }
  }
}
